package com.lry.basic.spring.ioc;


import com.lry.basic.spring.ioc.util.Common;
import com.lry.basic.spring.ioc.util.Objects;

/**
 * @author:刘仁有
 * @desc:
 * @email:953506233@qq.com
 * @data:2019/11/16
 */
public class AnnotationApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private PreBuildBeanFactory factory;
    public AnnotationApplicationContext(){
        this.factory = new PreBuildBeanFactory();
        //注册beanFactoryPostProcessor解析AppConfig
        registerBeanFactoryPostProcessor(new ConfigurationClassPostProcessor());
    }

    public AnnotationApplicationContext(Class<?>... annotatedClasses){
        this();
        register(annotatedClasses);
        refresh();
    }

    private void register(Class<?>[] annotatedClasses) {
        Objects.noEmpty(annotatedClasses,"require at least one config class");
        for (Class clazz:annotatedClasses) {
            //注册appConfig这个AnnotationGeneralBeanDefinition
            registerAnnotationBeanDefinition(clazz);
        }
    }

    private void registerAnnotationBeanDefinition(Class clazz) {
        doRegisterAnnotationBeanDefinition(null,clazz);
    }

    private void doRegisterAnnotationBeanDefinition(String beanName,Class clazz){
        AnnotationGeneralBeanDefinition abd = new AnnotationGeneralBeanDefinition(clazz);
        beanName = (beanName!=null?beanName: Common.toLowerCaseFirstOne(clazz.getSimpleName()));
        if(!factory.containsBeanDefinition(beanName)){
            registerBeanDefinition(beanName,abd);
        }
    }

    private void refresh() {
        try{
            invokeBeanFactoryPostProcessor();
            preInstantiateSingletons();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void invokeBeanFactoryPostProcessor() {
        for (BeanFactoryPostProcessor beanFactoryPostProcessor:factory.getBeanFactoryPostProcessors()) {
            if(beanFactoryPostProcessor instanceof ConfigurationClassPostProcessor){
                beanFactoryPostProcessor.postProcessorBeanFactory(factory);
            }
        }
    }

    //提前实例化非懒加载的单例bean
    public void preInstantiateSingletons() throws Exception{
        factory.preInstantiateSingletons();
    }

    @Override
    public Object getBean(String beanName) throws Exception {
        return factory.getBean(beanName);
    }

    @Override
    public void registerBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        factory.registerBeanPostProcessor(beanPostProcessor);
    }

    @Override
    public void registerBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) {
        factory.registerBeanFactoryPostProcessor(beanFactoryPostProcessor);
    }

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition bd) {
        factory.registerBeanDefinition(beanName,bd);
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return factory.getBeanDefinition(beanName);
    }

    @Override
    public void removeBeanDefinition(String beanName) {
        factory.removeBeanDefinition(beanName);
    }

    @Override
    public boolean containsBeanDefinition(String beanName) {
        return factory.containsBeanDefinition(beanName);
    }
}
